package inet.app.vod.subtitles;

import inet.app.vod.subtitles.SubtitleController.SubtitleListener;
import inet.app.vod.video.MyVideoView;
import android.os.CountDownTimer;
import android.util.Log;

public class SynchronizeSubtitle implements Runnable {

	private final static String TAG = "synchonize_subtitle";

	private final long INTERVAL_UPDATE_TIME_VIDEO = 2000; /*
														 * interval to get time
														 * video (miliseconds)
														 */
	private final int INTERVAL_UPDATE_SUBTITLE = 50; /*
													 * interval to update
													 * subtitles (miliseconds)
													 */

	private MyVideoView mVideoView;
	private long mVideoTimeCurrent; /* video time current get from video */
	private long mVideoTimeSystem; /* video time current get via system time */
	private CountDownTimer mCountDownTimer; /*
											 * coundown timer for synchronize
											 * subtitles
											 */

	TimedTextObject mTTO; /* TimedTextObject parse from subtitle file */
	Caption mCaptionSelect; /* Caption get from current time */
	Caption mCaptionCurrent = null; /* Caption is showing */

	SubtitleListener mSubtitleListener; /* Listener for update subtitle */

	boolean mLooping;
	boolean mRunning;
	Thread mThread;

	Integer mKeyLower;
	Caption mCaption;

	private void initData() {

		// init coundown timer
		mCountDownTimer = new CountDownTimer(INTERVAL_UPDATE_TIME_VIDEO,
				INTERVAL_UPDATE_SUBTITLE) {

			public void onTick(long millisUntilFinished) {

				/* Update time video via time system */
				mVideoTimeSystem += INTERVAL_UPDATE_SUBTITLE;

				Log.d(TAG, String.valueOf(mVideoTimeSystem));

				/* Get subtitle conrresponding with time video */
				mCaptionSelect = getSubtitleMatchTime((int) mVideoTimeSystem);
				if (mCaptionSelect != null) {
					if (mCaptionCurrent != mCaptionSelect) {
						/* update if subtitle has change */
						mSubtitleListener
								.onUpdateSubtitle(mCaptionSelect.content);
						mCaptionCurrent = mCaptionSelect;
					}
				} else {
					mSubtitleListener.onUpdateSubtitle("");
				}
			}

			public void onFinish() {
				android.util.Log.d("time_system", "finish");
			}
		};
	}

	public SynchronizeSubtitle(MyVideoView videoView, TimedTextObject tto,
			SubtitleListener subtitleListener) {

		this.mVideoView = videoView;
		this.mTTO = tto;
		this.mSubtitleListener = subtitleListener;

		initData();
	}

	/**
	 * start thead
	 */
	public void start() {
		mLooping = true;
		mRunning = true;

		mThread = new Thread(this);
		mThread.start();
	}

	/**
	 * resume thread
	 */
	public void onResume() {
		mRunning = true;
	}

	/**
	 * pause thread
	 */
	public void onPause() {
		mLooping = true;
		mRunning = false;
	}

	/**
	 * kill thread
	 */
	public void kill() {
		mLooping = false;
		mRunning = false;

		try {
			mThread.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		mThread = null;
	}

	@Override
	public void run() {

		while (mLooping) {

			Log.d(TAG, "synchronize subtitle running");
			if (mVideoView != null) {
				if (mRunning) {
					mVideoTimeCurrent = mVideoView.getCurrentPosition();
					startCoundownTimer();
				}
			}

			try {
				Thread.sleep(INTERVAL_UPDATE_TIME_VIDEO);
			} catch (InterruptedException e) {
				Log.e(TAG, e.toString());
			}
		}
	}

	/**
	 * Select subtitle match with time video
	 * 
	 * @param time
	 *            time current of video
	 * @return caption match with time video
	 */
	private Caption getSubtitleMatchTime(int time) {

		// Subtitle has startime is lower than time and highest
		mKeyLower = mTTO.captions.lowerKey(time);
		if (mKeyLower == null) {
			return null;
		}

		/* get caption if time in (caption.startTime, caption.endTime) */
		mCaption = mTTO.captions.get(mKeyLower);
		if (mCaption != null) {
			if (mCaption.start.mseconds <= time
					&& mCaption.end.mseconds >= time) {
				return mCaption;
			}
		}
		return null;
	}

	/**
	 * start coundown timer for synchonize subtitles
	 */
	private void startCoundownTimer() {

		mVideoTimeSystem = mVideoTimeCurrent;
		if (null != mCountDownTimer) {
			mCountDownTimer.cancel();
			mCountDownTimer.start();
		}
	}

	/**
	 * Stop coundown timer
	 */
	private void stopCoundownTimer() {

		if (null != mCountDownTimer) {
			mCountDownTimer.cancel();
		}
	}
}
